home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / imap / ANSI / c-client / mbox.c < prev    next >
C/C++ Source or Header  |  1996-05-15  |  7KB  |  200 lines

  1. /*
  2.  * Program:    MBOX mail routines
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    10 March 1992
  13.  * Last Edited:    15 May 1995
  14.  *
  15.  * Copyright 1995 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <errno.h>
  39. extern int errno;        /* just in case */
  40. #include "mail.h"
  41. #include "osdep.h"
  42. #include <sys/stat.h>
  43. #include <sys/time.h>
  44. #include "mbox.h"
  45. #include "bezerk.h"
  46. #include "misc.h"
  47.  
  48. /* MBOX mail routines */
  49.  
  50.  
  51. /* Driver dispatch used by MAIL */
  52.  
  53. DRIVER mboxdriver = {
  54.   "mbox",            /* driver name */
  55.   (DRIVER *) NIL,        /* next driver */
  56.   mbox_valid,            /* mailbox is valid for us */
  57.   bezerk_parameters,        /* manipulate parameters */
  58.   bezerk_find,            /* find mailboxes */
  59.   bezerk_find_bboards,        /* find bboards */
  60.   bezerk_find_all,        /* find all mailboxes */
  61.   bezerk_find_all_bboards,    /* find all bboards */
  62.   bezerk_subscribe,        /* subscribe to mailbox */
  63.   bezerk_unsubscribe,        /* unsubscribe from mailbox */
  64.   bezerk_subscribe_bboard,    /* subscribe to bboard */
  65.   bezerk_unsubscribe_bboard,    /* unsubscribe from bboard */
  66.   bezerk_create,        /* create mailbox */
  67.   bezerk_delete,        /* delete mailbox */
  68.   bezerk_rename,        /* rename mailbox */
  69.   mbox_open,            /* open mailbox */
  70.   bezerk_close,            /* close mailbox */
  71.   bezerk_fetchfast,        /* fetch message "fast" attributes */
  72.   bezerk_fetchflags,        /* fetch message flags */
  73.   bezerk_fetchstructure,    /* fetch message structure */
  74.   bezerk_fetchheader,        /* fetch message header only */
  75.   bezerk_fetchtext,        /* fetch message body only */
  76.   bezerk_fetchbody,        /* fetch message body section */
  77.   bezerk_setflag,        /* set message flag */
  78.   bezerk_clearflag,        /* clear message flag */
  79.   bezerk_search,        /* search for message based on criteria */
  80.   mbox_ping,            /* ping mailbox to see if still alive */
  81.   mbox_check,            /* check for new messages */
  82.   mbox_expunge,            /* expunge deleted messages */
  83.   bezerk_copy,            /* copy messages to another mailbox */
  84.   bezerk_move,            /* move messages to another mailbox */
  85.   bezerk_append,        /* append string message to mailbox */
  86.   bezerk_gc            /* garbage collect stream */
  87. };
  88.  
  89.                 /* prototype stream */
  90. MAILSTREAM mboxproto = {&mboxdriver};
  91.  
  92. /* MBOX mail validate mailbox
  93.  * Accepts: mailbox name
  94.  * Returns: our driver if name is valid, NIL otherwise
  95.  */
  96.  
  97. DRIVER *mbox_valid (char *name)
  98. {
  99.   char tmp[MAILTMPLEN];
  100.   char *s = mailboxfile (tmp,name);
  101.                 /* only consider INBOX */
  102.   return (s && !*s && bezerk_isvalid ("mbox",tmp)) ? &mboxdriver : NIL;
  103. }
  104.  
  105. /* MBOX mail open
  106.  * Accepts: stream to open
  107.  * Returns: stream on success, NIL on failure
  108.  */
  109.  
  110. MAILSTREAM *mbox_open (MAILSTREAM *stream)
  111. {
  112.   unsigned long i = 1;
  113.   unsigned long recent = 0;
  114.   char tmp[MAILTMPLEN];
  115.                 /* return prototype for OP_PROTOTYPE call */
  116.   if (!stream) return &mboxproto;
  117.                 /* change mailbox file name */
  118.   sprintf (tmp,"%s/mbox",myhomedir ());
  119.   fs_give ((void **) &stream->mailbox);
  120.   stream->mailbox = cpystr (tmp);
  121.                 /* open mailbox, snarf new mail */
  122.   if (!(bezerk_open (stream) && mbox_ping (stream))) return NIL;
  123.                 /* notify upper level of mailbox sizes */
  124.   mail_exists (stream,stream->nmsgs);
  125.   while (i <= stream->nmsgs) if (mail_elt (stream,i++)->recent) ++recent;
  126.   mail_recent (stream,recent);    /* including recent messages */
  127.   return stream;
  128. }
  129.  
  130. /* MBOX mail ping mailbox
  131.  * Accepts: MAIL stream
  132.  * Returns: T if stream alive, else NIL
  133.  * No-op for readonly files, since read/writer can expunge it from under us!
  134.  */
  135.  
  136. long mbox_ping (MAILSTREAM *stream)
  137. {
  138.   int fd,sfd;
  139.   char *s = sysinbox ();
  140.   unsigned long size;
  141.   struct stat sbuf;
  142.   char lock[MAILTMPLEN],lockx[MAILTMPLEN];
  143.   if (LOCAL && !stream->rdonly && !stream->lock) {
  144.     mm_critical (stream);    /* go critical */
  145.     if ((sfd = bezerk_lock (s,O_RDWR,NIL,lockx,LOCK_EX)) >= 0) {
  146.       fstat (sfd,&sbuf);    /* get size again now that locked */
  147.       if (size = sbuf.st_size) { /* get size of new mail if any */
  148.                 /* mail in good format? */
  149.     if (bezerk_isvalid_fd (sfd,lock)) {
  150.       lseek (sfd,0,L_SET);    /* rewind file */
  151.       read (sfd,s = (char *) fs_get (size + 1),size);
  152.       s[size] = '\0';    /* tie it off */
  153.       if ((fd = bezerk_lock (stream->mailbox,O_WRONLY|O_APPEND,NIL,lock,
  154.                  LOCK_EX)) >= 0) {
  155.         fstat (fd,&sbuf);    /* get current file size before write */
  156.         if ((write (fd,s,size) >= 0) && !fsync (fd))
  157.           ftruncate (sfd,0);/* flush from sysinbx */
  158.         else {        /* failed */
  159.           sprintf (LOCAL->buf,"New mail copy failed: %s",strerror (errno));
  160.           mm_log (LOCAL->buf,ERROR);
  161.           ftruncate (fd,sbuf.st_size);
  162.         }
  163.         bezerk_unlock (fd,NIL,lock);
  164.       }
  165.       fs_give ((void **) &s);/* either way, flush the poop now */
  166.     }
  167.     else {
  168.       sprintf (LOCAL->buf,"Invalid data in %s file",sysinbox ());
  169.       mm_log (LOCAL->buf,ERROR);
  170.     }
  171.       }
  172.                 /* all done with update */
  173.       bezerk_unlock (sfd,NIL,lockx);
  174.     }
  175.     mm_nocritical (stream);    /* release critical */
  176.   }
  177.   return bezerk_ping (stream);    /* do the bezerk routine now */
  178. }
  179.  
  180. /* MBOX mail check mailbox
  181.  * Accepts: MAIL stream
  182.  */
  183.  
  184. void mbox_check (MAILSTREAM *stream)
  185. {
  186.                 /* do local ping, then do bezerk routine */
  187.   if (mbox_ping (stream)) bezerk_check (stream);
  188. }
  189.  
  190.  
  191. /* MBOX mail expunge mailbox
  192.  * Accepts: MAIL stream
  193.  */
  194.  
  195. void mbox_expunge (MAILSTREAM *stream)
  196. {
  197.   bezerk_expunge (stream);    /* do expunge */
  198.   mbox_ping (stream);        /* do local ping */
  199. }
  200.